﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Xml;
using MOM.DB.Access;
using Mono.Data.Sqlite;

#region COPYRIGHT
/*
	COPYRIGHT © 2007 - 2008 Ulrik S. Andersson.
	
	This file is part of MOM.

    MOM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

    MOM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along with MOM.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

namespace MOM.DB.JSON
{
	public partial class Wikipedia : System.Web.UI.Page
	{
		
		protected void Page_Load(object sender, EventArgs e)
		{
			string action = Request.QueryString["a"];
			string query = Request.QueryString["q"];
		
			Response.ContentType = "text/plain";
			
			switch (action)
			{
				case "search":
					WebRequest request = HttpWebRequest.Create("http://en.wikipedia.org/w/api.php?action=opensearch&format=json&limit=25&search=" + Server.UrlEncode(query));
					WebResponse response = request.GetResponse();
					StreamReader reader = new StreamReader(response.GetResponseStream());
					string result = reader.ReadToEnd();
					if (result != null)
					{
						result = result.Substring(result.IndexOf(",[") + 1);
						result = result.Substring(0, result.Length - 1);
					}
					reader.Dispose();
					Response.Write(result);
					break;
				default:
					string artist = Request.QueryString["ar"];
					string text = null;
					using (SqliteServer conn = new SqliteServer("Default", true))
					{
						using (SqliteDataReader datareader = conn.GetDataReader("SELECT ArtistWiki FROM tblArtist WHERE ArtistName = '{0}'", artist))
						{
							if (datareader.Read())
							{
								if (datareader["ArtistWiki"] != DBNull.Value && (string)datareader["ArtistWiki"] != "")
								{
									string cache = (string)datareader["ArtistWiki"];
									DateTime cacheExp = new DateTime(long.Parse(cache.Substring(0, cache.IndexOf("|"))));
									if (DateTime.Now <= cacheExp)
									{
										text = cache.Substring(cache.IndexOf("|") + 1);
									}
								}
							}
						}
					}

					if (text == null)
					{
						text = GetWikiContent(query);
						//Get Intro
						if (text.IndexOf("==") > -1)
							text = text.Substring(0, text.IndexOf("=="));
						//Remove ref-tags
						text = Regex.Replace(text, "<ref[^>]+>.*?</ref>", "", RegexOptions.Singleline);
						//Remove comments
						text = Regex.Replace(text, "<!--.*?(?=-->)-->", "", RegexOptions.Singleline);
						//Fix HTML-tags
						text = text.Replace("<", "&lt;");
						text = text.Replace(">", "&gt;");
						//Remove Boxes 
						text = text.Replace("{{", "<");
						text = text.Replace("}}", ">");
						text = RemoveNestedTags(text);
						//Fix Internal Wiki Links
						text = Regex.Replace(text, @"\[\[[^\]\]]+\]\]", new MatchEvaluator(Wikipedia.FixWikiLinks), RegexOptions.Singleline);
						//Fix External Links
						text = Regex.Replace(text, @"\[[^\]]+\]", new MatchEvaluator(Wikipedia.FixExtLinks), RegexOptions.Singleline);
						//Fix bold
						text = Regex.Replace(text, @"'''([^''']+)'''", "<b>$1</b>", RegexOptions.Singleline);
						//Fix italics
						text = Regex.Replace(text, @"''([^'']+)''", "<i>$1</i>", RegexOptions.Singleline);
						//Revert HTML-tags
						text = text.Replace("&lt;", "<");
						text = text.Replace("&gt;", ">");
						//Remove line breaks
						text = text.Trim();
						text = text.Replace("\n", "<br/>");
						
						//Cache It
						using (SqliteServer conn = new SqliteServer("Default", true))
						{
							DateTime cacheExp = DateTime.Now.AddDays(7);
							string cache = cacheExp.Ticks.ToString() + "|" + text;
							conn.Execute("UPDATE tblArtist SET ArtistWiki = '{0}' WHERE ArtistName = '{1}'", cache, artist);
						}
					}

					Response.Write("{Content:\"" + text.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"}");
					break;
			}			
		}

		private string GetWikiContent(string query)
		{
            XmlDocument xml = RequestXml("http://en.wikipedia.org/w/api.php?action=query&prop=revisions&rvlimit=1&rvprop=content&format=xml&titles=" + query);
			XmlNodeList pages = xml.SelectNodes("/api/query/pages/page/revisions/rev");
			string text = "";
			if (pages.Count > 0)
			{
				text = pages[0].InnerText;
				if (text.ToUpper().StartsWith("#REDIRECT"))
				{
					text = text.Substring(text.IndexOf("[[") + 2);
					text = text.Substring(0, text.IndexOf("]]"));
					return GetWikiContent(Server.UrlEncode(text));
				}
			}
			return text;
		}

		private string RemoveNestedTags(string text)
		{
			string pattern = @"
				<
				(?>
					< (?<DEPTH>)
					|
					> (?<-DEPTH>)
					|
					.?
				)*
				(?(DEPTH)(?!))
				>";
			Regex re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
			return re.Replace(text, "");
		}
		
		static string FixWikiLinks(Match m)
		{
			string text = m.Value.Replace("[", "").Replace("]", "");
			string link = text;
			if (text.IndexOf("|") > -1)
			{
				string[] arr = text.Split('|');
				link = arr[0];
				text = arr[1];
			}
			return "<a href=\"http://en.wikipedia.org/wiki/" + link + "\" target=\"_blank\">" + text + "</a>";
		}

		static string FixExtLinks(Match m)
		{
			string text = m.Value.Replace("[", "").Replace("]", "");
			int split = text.IndexOf(' ');
			if (split > -1)
			{
				string url = text.Substring(0, split);
				text = text.Substring(split + 1);
				return "<a href=\"" + url + "\" target=\"_blank\">" + text + "</a>";
			}
			return "<a href=\"" + text + "\" target=\"_blank\">[1]</a>";
		}

		private XmlDocument RequestXml(string url)
        {
            WebClient wc = new WebClient();
            XmlDocument xmlDoc = new XmlDocument();
            MemoryStream memStream = null;

            try
            {
                wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                byte[] byteResponse = wc.DownloadData(url);
                memStream = new MemoryStream(byteResponse);
                xmlDoc = new XmlDocument();
                xmlDoc.Load(memStream);
            }
            finally
            {
                if (memStream != null)
                {
                    memStream.Flush();
                    memStream.Close();
                }
                wc.Dispose();
            }

            return xmlDoc;
        }		
	}
}